//
// Created by wangwanlong on 2024/11/5.
//

#ifndef MKAHYPAR_BLOCK_PENALTY_POLICY_H
#define MKAHYPAR_BLOCK_PENALTY_POLICY_H

#include "mkahypar/utils/typedef.h"
#include "mkahypar/utils/policy_registry.h"
//block惩罚策略
namespace mkahypar {
  //不做任何加权
  class NormalBlockPenalty : public meta::PolicyBase {
  public:
    MKAHYPAR_ATTRIBUTE_ALWAYS_INLINE static inline GainType exceed(NodeWeight &fpga_used,
                                                                   NodeWeight &fpga_bound){
      GainType gain = 0;
      //计算当前block的惩罚
      for(int i=0;i<fpga_used.size();++i){
        if(fpga_used[i] > fpga_bound[i])
          gain += (fpga_used[i] - fpga_bound[i]) * 100;
      }
      return gain;
    }
    MKAHYPAR_ATTRIBUTE_ALWAYS_INLINE static inline GainType computeMove(NodeWeight& hn_weight, NodeWeight &fpga_used,
                                                          NodeWeight &fpga_bound) {
      GainType gain = exceed(fpga_used,fpga_bound);
      if(gain == 0)
        return gain;
      //计算移除后超出惩罚
      for(int i=0;i<fpga_used.size();++i){
        if(fpga_used[i] - hn_weight[i] > fpga_bound[i])
          gain -= (fpga_used[i] - hn_weight[i] - fpga_bound[i]) * 100;//
      }
      return gain;//这个gain 一定是 >= 0
    }
    MKAHYPAR_ATTRIBUTE_ALWAYS_INLINE static inline GainType computeAdd(NodeWeight &hn_weight, NodeWeight &fpga_used,
                                                                        NodeWeight &fpga_bound) {
      GainType gain = exceed(fpga_used,fpga_bound);
      //计算添加后超出惩罚
      for(int i=0;i<fpga_used.size();++i){
        if(fpga_used[i] + hn_weight[i] > fpga_bound[i])
          gain -= (fpga_used[i] + hn_weight[i] - fpga_bound[i]) * 100;
      }
      return gain;//这个gain一定是 <= 0
    }
  };
}
#endif //MKAHYPAR_BLOCK_PENALTY_POLICY_H
